package com.linln.admin.handler;

import com.corundumstudio.socketio.AckRequest;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIOServer;
import com.corundumstudio.socketio.annotation.OnConnect;
import com.corundumstudio.socketio.annotation.OnDisconnect;
import com.corundumstudio.socketio.annotation.OnEvent;
import com.linln.admin.model.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 消息事件处理器
 *
 * @author XiongNeng
 * @version 1.0
 * @since 2018/1/19
 */
@Component
public class MessageEventHandler {

    private final SocketIOServer server;

    private static final Logger logger = LoggerFactory.getLogger(MessageEventHandler.class);

    //维护每个客户端的SocketIOClient
    private Map<String, List<SocketIOClient>> clients = new ConcurrentHashMap<>();

    @Autowired
    public MessageEventHandler(SocketIOServer server) {
        this.server = server;
    }

    //添加connect事件，当客户端发起连接时调用
    @OnConnect
    public void onConnect(SocketIOClient client) {
        if (client != null) {
            String username = client.getHandshakeData().getSingleUrlParam("username");
            String password = client.getHandshakeData().getSingleUrlParam("password");
            String userId = client.getHandshakeData().getSingleUrlParam("userId");
            String platformType = client.getHandshakeData().getSingleUrlParam("platformType");
            String sessionId = client.getSessionId().toString();

//            List<SocketIOClient> socketList = clients.get(userId);
            List<SocketIOClient> list = new ArrayList<>();
            list.add(client);
            clients.put(userId, list);
            logger.info("addList" + userId);
            logger.info("连接成功, username=" + username + ", password=" + password + ", sessionId=" + sessionId
                    + ", userId=" + userId + ", platformType=" + platformType);
            //通知上线
            sendOline(1);
        } else {
            logger.error("客户端为空");
        }
    }

    //添加@OnDisconnect事件，客户端断开连接时调用，刷新客户端信息
    @OnDisconnect
    public void onDisconnect(SocketIOClient client) {
        String username = client.getHandshakeData().getSingleUrlParam("username");
        String password = client.getHandshakeData().getSingleUrlParam("password");
        String sessionId = client.getSessionId().toString();
        String userId = client.getHandshakeData().getSingleUrlParam("userId");
        String platformType = client.getHandshakeData().getSingleUrlParam("platformType");
        logger.info("客户端断开连接, username=" + username + ", password=" + password + ", sessionId=" + sessionId
                + ", userId=" + userId + ", platformType=" + platformType);
        logger.info("客户端断开连接, sessionId=" + client.getSessionId().toString());
        client.disconnect();
        //通知上线
        sendOline(0);
        clients.remove(userId);
    }

    // 消息接收入口
    @OnEvent(value = "chatevent")
    public void onEvent(SocketIOClient client, AckRequest ackRequest, ChatMessage chat) {
        logger.info("接收到客户端消息");
        if (ackRequest.isAckRequested()) {
            // send ack response with data to client
            ackRequest.sendAckData("服务器回答chatevent, userName=" + chat.getUserName() + ",message=" + chat.getMessage());
        }
    }

    // 登录接口
    @OnEvent(value = "login")
    public void onLogin(SocketIOClient client, AckRequest ackRequest, LoginRequest message) {
        logger.info("接收到客户端登录消息");
        if (ackRequest.isAckRequested()) {
            // send ack response with data to client
            ackRequest.sendAckData("服务器回答login", message.getCode(), message.getBody());
        }
    }

    // 添加用户
    @OnEvent(value = "add user")
    public void onAddUser(SocketIOClient client, AckRequest ackRequest, String message) {
        logger.info("接收到客户端添加用户消息");
        if (ackRequest.isAckRequested()) {
            // send ack response with data to client
            ackRequest.sendAckData("服务器回答add user", message);
        }
    }

    @OnEvent("token")
    public void onToken(SocketIOClient client, SocketIOMessage message) {

    }

    /**
     * 新事务
     * @param client 客户端
     * @param message 消息
     */
    @OnEvent("newmessage")
    public void onAlert(SocketIOClient client, SocketIOMessage message) {
        //send to all users
        Collection<List<SocketIOClient>> clientsList = clients.values();
        for (List<SocketIOClient> list : clientsList) {
            for (SocketIOClient socketIOClient : list) {
                socketIOClient.sendEvent("newmessage", message);
            }
        }
    }

    /**
     * 通知所有在线客户端
     */
    public void sendAllUser() {
        Set<Map.Entry<String,List<SocketIOClient>>> entrySet = clients.entrySet();
        for (Map.Entry<String, List<SocketIOClient>> entry : entrySet) {
            String key = entry.getKey();
            List<SocketIOClient> value = entry.getValue();
            for (SocketIOClient socketIOClient : value) {
                SocketIOMessage message = new SocketIOMessage();
                String username = socketIOClient.getHandshakeData().getSingleUrlParam("username");
                message.setUsername(username);
                message.setMessage("send All user Msg" + key);
                socketIOClient.sendEvent("newmessage", message);
            }
        }
    }

    /**
     * 通知所有在线客户端-用户上线
     */
    public void sendOline(int onlineStatus) {
        Set<Map.Entry<String,List<SocketIOClient>>> entrySet = clients.entrySet();
        for (Map.Entry<String, List<SocketIOClient>> entry : entrySet) {
            String key = entry.getKey();
            List<SocketIOClient> value = entry.getValue();
            for (SocketIOClient socketIOClient : value) {
                SocketIOMessage message = new SocketIOMessage();
                String username = socketIOClient.getHandshakeData().getSingleUrlParam("username");
                message.setUsername(username);
                message.setMessage("用户上线：" + key+";online:"+onlineStatus);

                //
                Online online = new Online();
                online.setUserId(key);
                online.setOnlineStatus(onlineStatus);
                online.setUserName(username);
                PushBase pushBase = new PushBase();
                pushBase.setModule("online");
                pushBase.setContent(online);
                socketIOClient.sendEvent("newmessage", pushBase);
            }
        }
    }

}
